//! 命令行界面模块 - 提供用户与区块链系统的交互入口
//! 
//! ## 功能概述
//! 1. 提供菜单驱动的交互界面
//! 2. 管理本地钱包集合
//! 3. 处理区块链的创建、存储和加载
//! 4. 支持交易创建、挖矿和验证等核心操作

use std::io::{self, Write};
use chrono::{DateTime, Local}; // 删除 TimeZone};
use crate::blockchain::Blockchain;
use crate::wallet::Wallet;
use crate::transaction::Transaction;
//use crate::storage::{save_blockchain, load_blockchain};

/// 命令行接口管理器
/// 
/// # 数据结构
/// - `wallets`: 当前会话管理的钱包集合  
/// - `blockchain`: 当前操作的区块链实例  
/// 
/// # 持久化说明
/// - 退出时自动保存区块链到 `blockchain.json`
/// - 钱包信息仅内存存储（重启后需重新创建）
pub struct CLI {
    wallets: Vec<Wallet>,
    blockchain: Blockchain,
}

impl CLI {
    /// 初始化 CLI 环境
    /// 
    /// # 启动流程
    /// 1. 尝试从 `blockchain.json` 加载现有区块链  
    /// 2. 文件不存在或损坏时创建新链  
    /// 3. 初始化空钱包列表  
    /// 
    /// # 参数
    /// - 默认使用难度系数 4 初始化区块链  
    pub fn new() -> Self {
        CLI {
            wallets: Vec::new(),
            // 从存储加载或创建新链（文件名为 blockchain.json）
            //blockchain: load_blockchain("blockchain.json", 4),
            blockchain: Blockchain::load("blockchain.json")
                .unwrap_or_else(|_| Blockchain::new(4)), // 加载失败时创建新链
        }
    }

    /// 主运行循环 - 提供交互式菜单
    /// 
    /// # 操作流程
    /// 1. 打印菜单选项  
    /// 2. 读取用户输入  
    /// 3. 执行对应操作  
    /// 4. 循环直到选择退出  
    /// 
    /// # 菜单选项说明
    /// | 选项 | 功能                     | 所需前提条件           |
    /// |------|--------------------------|-----------------------|
    /// | 1    | 创建新钱包               | 无                    |
    /// | 2    | 查看完整区块链           | 需已有区块            |
    /// | 3    | 创建并签名交易           | 需存在发送者钱包      |
    /// | 4    | 挖矿获得奖励             | 需有未打包交易        |
    /// | 5    | 验证区块链完整性         | 需已初始化区块链      |
    /// | 6    | 退出并保存               | 无                    |
    pub fn run(&mut self) {
        loop {
            println!("\n=== 区块链系统菜单 ===");
            self.print_menu();
            
            match self.read_input().as_str() {
                "1" => self.create_wallet(),
                "2" => self.view_blockchain(), "2s" => self.view_blockchain_safe(),
                "3" => self.add_transaction(),
                "4" => self.mine_block(),
                "5" => self.validate_blockchain(),
		"7" => self.bbs_menu(), // 新增 BBS 子菜单
                "6" => break,
                _ => println!("⚠️ 无效选项，请输入 1-6 的数字"),
            }
        }
        
        // 退出时自动保存
        self.save_data();
    }

    // 添加 BBS 子菜单
    fn bbs_menu(&mut self) {
        println!("\n=== BBS 功能 ===");
        println!("1. 创建新帖子");
        println!("2. 查看论坛内容");
        // ...其他 BBS 功能
    }

    /// 打印菜单选项（私有方法）
    fn print_menu(&self) {
        println!("1. 创建钱包");
        println!("2. 查看区块链[s安全显示]");
        println!("3. 添加交易");
        println!("4. 挖矿");
        println!("5. 验证区块链");
        println!("7. BBS功能"); // 新增选项
        println!("6. 退出");
        print!("请输入选择: ");
        io::stdout().flush().unwrap(); // 立即输出缓冲区
    }

    /// 读取用户输入（私有工具方法）
    /// 
    /// # 返回
    /// 去除首尾空白后的输入字符串  
    /// 
    /// # 错误处理
    /// - 读取失败时返回空字符串
    fn read_input(&self) -> String {
        let mut input = String::new();
        io::stdin().read_line(&mut input)
            .expect("❌ 读取输入失败");
        input.trim().to_string()
    }

    /// ### 功能 1: 创建新钱包
    /// 
    /// # 用户流程
    /// 1. 生成 ED25519 密钥对  
    /// 2. 显示钱包地址（公钥）  
    /// 3. 将钱包添加到内存列表  
    /// 
    /// # 输出示例
    /// ```text
    /// 新钱包创建成功，地址: 8a7c3f...
    /// ```
    fn create_wallet(&mut self) {
        let wallet = Wallet::new();
        println!("✅ 新钱包创建成功，地址: {}", wallet.public_key());
        self.wallets.push(wallet);
    }

    /// ### 功能 2: 查看区块链
    /// 
    /// # 显示内容
    /// - 以美观格式打印每个区块的详细信息  
    /// - 按区块高度顺序显示（从创世块开始）  
    /// 
    /// # 显示字段
    /// - 区块高度  
    /// - 时间戳  
    /// - 交易数量  
    /// - 区块哈希  
    /// - 前驱哈希  
    /// 
    /// # 注意事项
    /// - 空区块链会显示无输出
    fn view_blockchain_safe(&self) {
        println!("\n=== 区块链数据 ===");
        for (idx, block) in self.blockchain.chain().iter().enumerate() {
            println!("\n🔗 区块 #{}", idx);
            println!("  高度: {}", block.index);
            
            // 时间戳安全转换
            let dt = match block.timestamp {
                0 => Local::now().into(), // 处理创世区块默认值
                ts => DateTime::from_timestamp(ts, 0)
                    .unwrap_or_else(|| Local::now().into()) // 处理无效时间戳
            };
            println!("  时间: {}", dt.format("%Y-%m-%d %H:%M:%S"));

            println!("  交易数: {}", block.transactions.len());
            
            // 哈希显示安全函数
            let hash_safe_show = |s: &str| -> String {
                let show_len = s.len().min(16); // 动态计算显示长度
                if s.is_empty() {
                    "空".to_string()
                } else {
                    format!("{}... (总长{}字节)", &s[..show_len], s.len())
                }
            };
            
            println!("  当前哈希: {}", hash_safe_show(&block.hash));
            println!("  前驱哈希: {}", hash_safe_show(&block.previous_hash));
            println!("  Merkle根: {}", hash_safe_show(&block.merkle_root));
        }
    }

    /// ### 功能 2: 查看区块链
    ///
    /// 完整现实, 不安全.
    fn view_blockchain(&self) {
        for block in self.blockchain.chain() {
            println!("{:#?}", block);
        }
    }

    /// ### 功能 3: 添加交易
    /// 
    /// # 用户流程
    /// 1. 输入发送者地址（必须为本地钱包）  
    /// 2. 输入接收者地址  
    /// 3. 输入转账金额（整数）  
    /// 4. 自动签名并加入交易池  
    /// 
    /// # 输入验证
    /// - 发送者必须存在于本地钱包  
    /// - 金额必须为正整数  
    /// 
    /// # 错误提示
    /// - "未找到发送者钱包" → 需先创建钱包  
    /// - "交易已添加" → 成功提示
    fn add_transaction(&mut self) {
        println!("\n=== 创建新交易 ===");
        
        // 收集发送者地址
        let sender = self.prompt_input("发送者地址: ");
        // 查找对应的钱包实例
        let wallet = match self.wallets.iter().find(|w| w.public_key() == sender) {
            Some(w) => w,
            None => {
                println!("❌ 未找到发送者钱包，请先创建钱包");
                return;
            }
        };

        // 收集接收者地址
        let receiver = self.prompt_input("接收者地址: ");
        
        // 收集并验证金额
        let amount = loop {
            match self.prompt_input("金额: ").parse::<u64>() {
                Ok(n) if n > 0 => break n,
                _ => println!("❌ 金额必须为正整数，请重新输入"),
            }
        };

        // 创建并签名交易
        let mut tx = Transaction::new(sender, receiver, amount);
        tx.sign(wallet.key_pair());
        self.blockchain.add_transaction(tx);
        
        println!("✅ 交易已添加到待处理池");
    }

    /// ### 功能 4: 挖矿
    /// 
    /// # 用户流程
    /// 1. 输入矿工奖励地址  
    /// 2. 打包所有有效交易  
    /// 3. 添加矿工奖励交易（50代币）  
    /// 4. 执行工作量证明  
    /// 
    /// # 输入要求
    /// - 地址需符合公钥格式（自动校验）  
    /// 
    /// # 注意事项
    /// - 需要至少1笔交易（含奖励交易）才会生成新区块  
    /// - 挖矿时间取决于难度设置
    fn mine_block(&mut self) {
        println!("\n=== 开始挖矿 ===");
        let addr = self.prompt_input("矿工奖励地址: ");
        
        // 执行挖矿操作
        self.blockchain.add_block(addr.trim());
        
        println!("✅ 新区块已成功挖出！");
        println!("   当前链高度: {}", self.blockchain.chain().len());
    }

    /// ### 功能 5: 验证区块链
    /// 
    /// # 验证内容
    /// 1. 创世区块规则验证  
    /// 2. 哈希链连续性验证  
    /// 3. 工作量证明有效性  
    /// 
    /// # 输出说明
    /// - "区块链有效性: true" → 数据完整  
    /// - "区块链有效性: false" → 存在篡改  
    fn validate_blockchain(&self) {
        let valid = self.blockchain.is_valid();
        println!("\n🔍 区块链有效性: {}", valid);
        if !valid {
            println!("⚠️  警告: 区块链数据可能被篡改或损坏！");
        }
    }

    /// ### 退出时自动保存数据
    /// 
    /// # 保存内容
    /// - 区块链数据 → blockchain.json  
    /// - 钱包信息 → 不保存（仅内存）  
    /// 
    /// # 文件格式
    /// - 使用 JSON 格式序列化  
    /// - 包含完整区块列表
    fn save_data(&self) {
        //save_blockchain(&self.blockchain, "blockchain.json");
        self.blockchain.save("blockchain.json")
	    .expect("💾 区块链数据保存失败");
        //println!("\n💾 区块链数据已保存到 blockchain.json");
    }

    /// 通用输入提示工具（私有方法）
    fn prompt_input(&self, prompt: &str) -> String {
        print!("{}", prompt);
        io::stdout().flush().unwrap();
        self.read_input()
    }
}
